package lumis.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import lumis.portal.PortalException;


/**
 * Utility used to process collections in blocks.
 * <p>
 * Currently each block is fixed in a maximum size of 1000 elements.
 * 
 * @param <T> the type of the collection elements.
 *
 * @version $Revision: 10458 $ $Date: 2009-06-02 15:49:09 -0300 (Tue, 02 Jun 2009) $
 * @since 4.2.2.090330
 */
public class CollectionExecutor<T>
{
	/**
	 * Interface that is implemented to provide the command for executing a 
	 * block of a collection.
	 * 
	 * @param <T> the type of the collection elements.
	 *
	 * @see CollectionExecutor
	 * 
	 * @version $Revision: 10458 $ $Date: 2009-06-02 15:49:09 -0300 (Tue, 02 Jun 2009) $
	 * @since 4.2.2.090330
	 */
	public static interface IIterationCommand<T>
	{
		/**
		 * Method call to execute a list of items, that is a sub-list of the
		 * original collection to be processed.
		 * @param subItems the sub-list of the original collection.
		 * @see CollectionExecutor
		 * 
		 * @since 4.2.2.090330
		 */
		public void execute(List<T> subItems) throws PortalException;
	}

	/**
	 * The maximum number of element in each iteration that calls 
	 * {@link IIterationCommand#execute(List)}.
	 * @since 4.2.2.090330
	 */
	private int maxElementsEachIteration = 1000;
	
	/**
	 * The collection this executor will process.
	 * @since 4.2.2.090330
	 */
	private Collection<? extends T> items;
	
	/**
	 * Creates a new executor.
	 * @param items the collection to be processed in blocks.
	 * @since 4.2.2.090330
	 */
	public CollectionExecutor(Collection<? extends T> items)
	{
		this.items = items;
	}

	/**
	 * Executes a command on the collection in this executor. 
	 * {@link IIterationCommand#execute(List)} is called multiple times, 
	 * given as argument a sublist of the collection in this executor, in the
	 * same order as the collection's iterator. 
	 * @param command the command to be executed.
	 * @since 4.2.2.090330
	 */
	public void execute(IIterationCommand<T> command) throws PortalException
	{
		List<T> itemsList = new ArrayList<T>(items);
		
		// control variables
		int begin;
		int end = 0;
		while(end < itemsList.size())
		{
			// next block
			begin = end;
			end = (end + maxElementsEachIteration) < itemsList.size() ? end + maxElementsEachIteration : itemsList.size();
			
			// execute on the current section
			command.execute(itemsList.subList(begin, end));
		}
	}
}

